﻿using System;
using System.Data;
using System.Data.Common;
using System.EnterpriseServices;
using System.Linq;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Unis.Framework.Core.Exceptions;
using Unis.Framework.Core.Utility;
using Unis.Framework.ORM.BaseDefiniens.Enums;
using Unis.Framework.ORM.Mapping;
using Unis.ORM.Mapping;

namespace Unis.Framework.ORM.Persistence
{
    [Transaction(TransactionOption.Supported)]
    public class EntityDistributedHelper
    {
        // Fields
        private static readonly string LAST_MODIFIED_DATE_PROPERTY = "LAST_MODIFY_DATE";

        // Methods
        public void CheckEntityCanSave(object entity)
        {
            if (((entity != null) && !(entity is DataRow)) && Reflection.CheckObjectExistsProperty(entity, LAST_MODIFIED_DATE_PROPERTY))
            {
                DateTime time = this.getCurrentEditDate(entity);
                DateTime time2 = this.getEntityLastModifiedDate(entity);
                if (DateTime.Compare(time, time2) < 0)
                {
                    throw new APPException("当前单据可能已被其它用户修改,本次操作不成功！", APPMessageType.DisplayToUser);
                }
            }
        }

        private DateTime getCurrentEditDate(object entity)
        {
            object obj2 = Reflection.GetObjectProperty(entity, LAST_MODIFIED_DATE_PROPERTY);
            if (obj2 == null)
            {
                return DateTime.MinValue;
            }
            return Convert.ToDateTime(obj2);
        }

        private DateTime getEntityLastModifiedDate(object entity)
        {
            Type t = entity.GetType();
            ModelMappingInfo modelMappingInfo = AttMappingManager.Instance.GetModelMappingInfo(t);
            if (string.IsNullOrEmpty(modelMappingInfo.MapTable))
            {
                throw new APPException(string.Format("数据实体{0} 配置有误，没有指定映射到的表。", t.FullName), APPMessageType.SysErrInfo);
            }
            if ((modelMappingInfo.PrimaryKeys == null) || (modelMappingInfo.PrimaryKeys.Count != 1))
            {
                throw new APPException(string.Format("数据实体{0} 配置有误，没有指定主键或者不是单一主键配置。", t.FullName), APPMessageType.SysErrInfo);
            }
            FieldPropertyInfo info2 = modelMappingInfo.PrimaryKeys.Values.First<FieldPropertyInfo>();
            object obj2 = Reflection.GetObjectProperty(entity, info2.PropertyName);
            if (obj2 == null)
            {
                return DateTime.MinValue;
            }
            string query = string.Format("SELECT {0} FROM {1} WHERE {2}='{3}'", new object[] { LAST_MODIFIED_DATE_PROPERTY, modelMappingInfo.MapTable, info2.FieldName, obj2.ToString() });
            Database database = DatabaseHelper.CreateDatabase();
            DbCommand sqlStringCommand = database.GetSqlStringCommand(query);
            object obj3 = database.ExecuteScalar(sqlStringCommand);
            if ((obj3 == null) || (obj3 == DBNull.Value))
            {
                return DateTime.MinValue;
            }
            sqlStringCommand.Dispose();
            return Convert.ToDateTime(obj3);
        }

        public DbCommand GetSaveLastModifiedDateCommand(Database db, object entity)
        {
            if (!Reflection.CheckObjectExistsProperty(entity, LAST_MODIFIED_DATE_PROPERTY))
            {
                return null;
            }
            Type t = entity.GetType();
            ModelMappingInfo modelMappingInfo = AttMappingManager.Instance.GetModelMappingInfo(t);
            if (string.IsNullOrEmpty(modelMappingInfo.MapTable))
            {
                throw new APPException(string.Format("数据实体{0} 配置有误，没有指定映射到的表。", t.FullName), APPMessageType.SysErrInfo);
            }
            if ((modelMappingInfo.PrimaryKeys == null) || (modelMappingInfo.PrimaryKeys.Count != 1))
            {
                throw new APPException(string.Format("数据实体{0} 配置有误，没有指定主键或者不是单一主键配置。", t.FullName), APPMessageType.SysErrInfo);
            }
            FieldPropertyInfo info2 = modelMappingInfo.PrimaryKeys.Values.First<FieldPropertyInfo>();
            DatabaseType databaseType = DatabaseConfigurationScope.GetDatabaseType(db);
            string str = string.Empty;
            switch (databaseType)
            {
                case DatabaseType.MSSQLServer:
                    str = "GetDate()";
                    break;

                case DatabaseType.Oracle:
                    str = "SysDate";
                    break;

                case DatabaseType.Sqlite:
                    str = "datetime(CURRENT_TIMESTAMP,'localtime')";
                    break;

                case DatabaseType.MySql:
                    str = "Now()";
                    break;

                default:
                    throw new APPException(string.Format("在获取数据库系统时间时,数据库类型{0} 还没有进行相应的处理", databaseType.ToString()), APPMessageType.SysErrInfo);
            }
            object obj2 = Reflection.GetObjectProperty(entity, info2.PropertyName);
            string query = string.Format("UPDATE {0} SET {1}= {2} WHERE {3}='{4}'", new object[] { modelMappingInfo.MapTable, LAST_MODIFIED_DATE_PROPERTY, str, info2.FieldName, obj2.ToString() });
            return db.GetSqlStringCommand(query);
        }

        // Properties
        public static EntityDistributedHelper NewInstance
        {
            get
            {
                return new EntityDistributedHelper();
            }
        }
    }
}
